Per quanto riguarda l’analisi generale del dataset, cercando un modo intelligente per identificare gli utenti influenti, ho estratto questo dataset dove ogni riga è un utente, mentre ogni colonna è una informazione globale per quel determinato utente. Ad esempio, utente X ha fatto 5 tweet nei 7 giorni di cui noi teniamo i dati, dati questi 5 tweet ho estratto informazioni come: numero di retweet, risposte, citazioni totali ricevuti, andamento del numero di following, followers ecc.

#carica il dataset
Sentiment_fr_tweet_2023 <- read_csv2("C:/Users/rosar/Desktop/UNISA/Magistrale - Informatica/SAD/Sentiment_fr_tweet_2023.csv")
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
##   dat <- vroom(...)
##   problems(dat)
## Rows: 112958 Columns: 30
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr  (17): username, acctdesc, location, text, hashtags, language, original_...
## dbl   (7): userid, following, followers, totaltweets, tweetid, retweetcount,...
## lgl   (3): coordinates, is_retweet, is_quote_status
## dttm  (3): usercreatedts, tweetcreatedts, extractedts
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dataset <- Sentiment_fr_tweet_2023
dataset <- dataset %>%
  mutate(
    userid = as.character(userid),
    username = as.character(username),
    acctdesc = as.character(acctdesc),
    location = as.character(location),
    following = as.numeric(following),
    followers = as.numeric(followers),
    totaltweets = as.numeric(totaltweets),
    tweetid = as.character(tweetid),
    retweetcount = as.numeric(retweetcount),
    favorite_count = as.numeric(favorite_count),
    text = as.character(text),
    language = as.character(language),
    favorite_count = as.numeric(favorite_count),
    
    # Conversione corretta di is_retweet
    is_retweet = ifelse(as.numeric(is_retweet) == 1, TRUE, FALSE),
    is_retweet = as.logical(is_retweet), # Garantire che sia booleano

    original_tweet_id = format(as.numeric(original_tweet_id), scientific = FALSE),
    original_tweet_userid = format(as.numeric(original_tweet_userid), scientific = FALSE),
    original_tweet_username = as.character(original_tweet_username),
    
    in_reply_to_status_id = format(as.numeric(in_reply_to_status_id), scientific = FALSE),
    in_reply_to_user_id = format(as.numeric(in_reply_to_user_id), scientific = FALSE),
    in_reply_to_screen_name = as.character(in_reply_to_screen_name),
    
    is_quote_status = as.logical(as.numeric(is_quote_status)), # Conversione booleana
    quoted_status_id = format(as.numeric(quoted_status_id), scientific = FALSE),
    quoted_status_userid = format(as.numeric(quoted_status_userid), scientific = FALSE),
    quoted_status_username = as.character(quoted_status_username),
    
    sentiment = as.factor(sentiment),
    score = as.numeric(score)
  )


# Partizionamento varie tipologie di tweet
dfPartizionati <- dataset %>%
  mutate(
    Tipo_Tweet = case_when(
      # Retweet
      is_retweet == TRUE ~ "Retweet",
      # Risposte
      in_reply_to_status_id != "                  0" & is_retweet == FALSE ~ "Risposta",
      # Citazioni
      is_quote_status == TRUE & is_retweet == FALSE & in_reply_to_status_id == "                  0" ~ "Citazione",
      # Tweet Normali
      TRUE ~ "Normale"
    )
  )

# Dataset globale per utente
#
# Aggregazione per utente
dfUtenti <- dfPartizionati %>%
  group_by(userid, username) %>%
  summarise(
    # Conteggio tweet per categoria
    Totale_Tweet = n(),
    Totale_Retweet = sum(Tipo_Tweet == "Retweet"),
    Totale_Risposte = sum(Tipo_Tweet == "Risposta"),
    Totale_Citazioni = sum(Tipo_Tweet == "Citazione"),
    Totale_Normali = sum(Tipo_Tweet == "Normale"),
    
    # Andamenti temporali
    Following_Min = min(following, na.rm = TRUE),
    Following_Max = max(following, na.rm = TRUE),
    Followers_Min = min(followers, na.rm = TRUE),
    Followers_Max = max(followers, na.rm = TRUE),
    Totaltweets_Min = min(totaltweets, na.rm = TRUE),
    Totaltweets_Max = max(totaltweets, na.rm = TRUE),
    
    # Sentiment
    Sentiment_Pos = mean(score[sentiment == "pos"], na.rm = TRUE),
    Sentiment_Neu = mean(score[sentiment == "neu"], na.rm = TRUE),
    Sentiment_Neg = mean(score[sentiment == "neg"], na.rm = TRUE),
    
    # Intervallo temporale dei dati
    Data_Inizio = min(tweetcreatedts, na.rm = TRUE),
    Data_Fine = max(tweetcreatedts, na.rm = TRUE),
    
    # Interazioni calcolate dai tipi di tweet
    Totale_Interazioni = Totale_Risposte + Totale_Citazioni,
    
    # Coinvolgimento
    Media_Retweet = mean(retweetcount, na.rm = TRUE),
    Media_Like = mean(favorite_count, na.rm = TRUE),
    Totale_Retweet = sum(retweetcount, na.rm = TRUE),
    Totale_Like = sum(favorite_count, na.rm = TRUE),
    
    # Rapporto attività/account
    Giorni_Attivi = as.numeric(difftime(max(tweetcreatedts, na.rm = TRUE), min(tweetcreatedts, na.rm = TRUE), units = "days")),
    Tweet_Giornalieri_Medi = Totale_Tweet / Giorni_Attivi,
    Rapporto_Follower_Following = mean(followers / following, na.rm = TRUE),
    
    # Distribuzione temporale delle attività
    Orario_Preferito = names(sort(table(tweetcreatedts), decreasing = TRUE)[1])
  ) %>%
  ungroup()
## `summarise()` has grouped output by 'userid'. You can override using the
## `.groups` argument.
# Calcolo delle metriche di attività e influenza e classificazione
dfUtenti <- dfUtenti %>%
  mutate(
    # Metriche di Attività
    Interazioni_Totali = Totale_Retweet + Totale_Risposte + Totale_Citazioni,
    Coerenza_Temporale = Giorni_Attivi / Totale_Tweet,
    
    # Metriche di Influenza
    Engagement_Totale = Totale_Retweet + Totale_Like,
    Engagement_Relativo = Engagement_Totale / Followers_Max,
    Media_Retweet_Per_Tweet = Totale_Retweet / Totale_Tweet,
    Media_Like_Per_Tweet = Totale_Like / Totale_Tweet,
    
    # Classificazione per Attività
    Classe_Attivita = case_when(
      Totale_Tweet >= quantile(Totale_Tweet, 0.75) ~ "Alta",
      Totale_Tweet >= quantile(Totale_Tweet, 0.50) ~ "Moderata",
      TRUE ~ "Bassa"
    ),
    
    # Classificazione per Influenza
    Classe_Influenza = case_when(
      Engagement_Relativo >= quantile(Engagement_Relativo, 0.75, na.rm = TRUE) ~ "Alta",
      Engagement_Relativo >= quantile(Engagement_Relativo, 0.50, na.rm = TRUE) ~ "Moderata",
      TRUE ~ "Bassa"
    )
  )

1. Distribuzioni di Base

Distribuzione dei Tweet per Tipo Motivo: Vogliamo analizzare il numero totale di tweet per ciascun tipo (ad esempio, normali, retweet, citazioni) per capire quale tipo è predominante nella nostra base dati.

-   Grafico a barre: distribuzione di `Totale_Retweet`, `Totale_Risposte`, `Totale_Citazioni`, `Totale_Normali`.
  dfTipoTweet <- dfPartizionati %>%
  group_by(Tipo_Tweet) %>%
  summarise(Totale = n())


Q1_25 = quantile(dfPartizionati$retweetcount , 0.25)
Q3_75 = quantile(dfPartizionati$retweetcount , 0.75)

# Calcolo IQR e i limiti perdefinire gli outlier (k=1.5 tutti, k=3 solo i grandi)
IQR_value <- Q3_75 - Q1_25
lower_limit_standard <- Q1_25 - 1.5 * IQR_value
upper_limit_standard <- Q3_75 + 1.5 * IQR_value
lower_limit_large <- Q1_25 - 3 * IQR_value
upper_limit_large <- Q3_75 + 3 * IQR_value

data_no_outliers <- dfPartizionati %>%
filter(retweetcount >= lower_limit_large & retweetcount <= upper_limit_large) %>%
mutate(type = "Senza Outliers")

ggplot(dfTipoTweet, aes(x = Tipo_Tweet, y = Totale, fill = Tipo_Tweet)) +
  geom_bar(stat = "identity") +
  labs(title = "Distribuzione dei Tweet per Tipo", x = "Tipo di Tweet", y = "Totale") +
  theme_minimal()

Il grafico mostra che un particolare tipo di tweet (retweet) è molto più comune degli altri, possiamo concludere che l’attività dell’utenza è orientata principalmente verso quel tipo di interazione.

Motivo: Gli outliers possono distorcere la comprensione della distribuzione generale dei retweet. Rimuovendo gli outliers, possiamo analizzare meglio la tendenza centrale.

# Rimuovi gli outliers dal boxplot
ggplot(data_no_outliers, aes(x = Tipo_Tweet, y = retweetcount, fill = Tipo_Tweet)) +
  geom_boxplot(outlier.shape = NA) +  # Nasconde i punti degli outliers
  labs(title = "Distribuzione dei Retweet Standardizzati per Tipo di Tweet", 
       x = "Tipo di Tweet", 
       y = "Numero di Retweet (Standardizzati)") +
  theme_minimal()

Il grafico mostra che il numero di retweet è significativamente più alto, possiamo dedurre che quel tipo di contenuto è più condivisibile.

Motivo: Analizziamo la distribuzione dei like totali per capire il livello di engagement dei post nella nostra base dati.

  # **Distribuzione delle Metriche di Engagement**:

    # Calcolo dei limiti per Totale_Like
Q1_like <- quantile(dfUtenti$Totale_Tweet, 0.25, na.rm = TRUE)
Q3_like <- quantile(dfUtenti$Totale_Tweet, 0.75, na.rm = TRUE)
IQR_like <- Q3_like - Q1_like
lower_limit_like <- Q1_like - 1.5 * IQR_like
upper_limit_like <- Q3_like + 1.5 * IQR_like

# Calcolo dei limiti per Totale_Retweet
Q1_retweet <- quantile(dfUtenti$Totale_Retweet, 0.25, na.rm = TRUE)
Q3_retweet <- quantile(dfUtenti$Totale_Retweet, 0.75, na.rm = TRUE)
IQR_retweet <- Q3_retweet - Q1_retweet
lower_limit_retweet <- Q1_retweet - 1.5 * IQR_retweet
upper_limit_retweet <- Q3_retweet + 1.5 * IQR_retweet

# Filtrare i dati senza outliers
dfUtenti_filtrato <- dfUtenti %>%
  filter(
    Totale_Like >= lower_limit_like & Totale_Like <= upper_limit_like,
    Totale_Retweet >= lower_limit_retweet & Totale_Retweet <= upper_limit_retweet
  )

# Istogramma di `Totale_Like`
ggplot(dfUtenti_filtrato, aes(x = Totale_Like)) +
  geom_histogram(binwidth = 1, fill = "blue", color = "white") +
  labs(title = "Distribuzione dei Like Totali (Senza Outliers)", x = "Totale Like", y = "Frequenza") +
  theme_minimal()

Se il grafico mostra una distribuzione asimmetrica, potrebbe significare che ci sono pochi utenti con un numero molto alto di like, mentre la maggioranza ha numeri più modesti.

Motivo: Vogliamo capire come sono distribuiti i retweet totali nella nostra base dati per valutare il potenziale virale del contenuto.

# Istogramma di `Totale_Retweet`
ggplot(dfUtenti_filtrato, aes(x = Totale_Retweet)) +
  geom_histogram(binwidth = 10, fill = "red", color = "white") +
  labs(title = "Distribuzione dei Retweet Totali (Senza Outliers)", x = "Totale Retweet", y = "Frequenza") +
  theme_minimal()

Il numero di retweet segue una chiara distribuzione quindi i post hanno una frequenza di retweet generalmente bassa che segue una distribuzione esponenziale/poisson

Motivo: Studiamo la relazione tra il numero massimo di utenti seguiti (following) e il numero massimo di follower per capire eventuali correlazioni.

  # **Distribuzione dei Followers e Following**:

    #-   Scatter plot per il rapporto `Rapporto_Follower_Following`.
ggplot(dfUtenti, aes(x = Following_Max, y = Followers_Max)) +
  geom_point(color = "purple") +
  labs(title = "Rapporto Followers-Following", x = "Massimo Following", y = "Massimo Followers") +
  theme_minimal()

Se osserviamo una relazione positiva, significa che gli utenti che seguono molti account tendono anche ad avere più follower, suggerendo una relazione reciproca tra queste metriche.

Motivo: Vogliamo analizzare come il numero di tweet pubblicati da un utente influisce sul numero di follower massimi che possiede.

ggplot(dfUtenti, aes(x = Totale_Tweet, y = Followers_Max)) +
  geom_point(color = "green", alpha = 0.7) +
  labs(title = "Rapporto Followers-Tweet",
       x = "Totale Tweet",
       y = "Massimo Followers") +
  theme_minimal()

Se il grafico mostra che gli utenti con più tweet tendono ad avere più follower, potrebbe suggerire che l’attività su Twitter è un fattore determinante per aumentare il seguito.

Motivo: Vogliamo osservare come l’attività massima in termini di tweet degli utenti sia cambiata nel tempo per identificare tendenze o picchi specifici.

### **2. Analisi Temporali**

 # **Evoluzione dell'Attività degli Utenti**
# Line plot di Totaltweets_Max nel tempo
ggplot(dfUtenti, aes(x = Data_Fine, y = Totaltweets_Max)) +
  geom_line(color = "blue", size = 1) +
  labs(
    title = "Evoluzione dell'Attività degli Utenti nel Tempo",
    x = "Data Fine",
    y = "Totale Tweet Massimi"
  ) +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Il grafico mostra una andamento oscillante, in quanto in base alla giornata ci sono stati più o meno tweet.

Motivo: Analizziamo quando gli utenti tendono a essere più attivi in termini di orari e giorni della settimana per individuare pattern temporali.

# Heatmap della distribuzione dei tweet per orario o giorno della settimana
# Prima prepariamo i dati per la heatmap
dfHeatmap <- dataset %>%
  mutate(
    Giorno_Settimana = wday(tweetcreatedts, label = TRUE),
    Ora = hour(tweetcreatedts)
  ) %>%
  group_by(Giorno_Settimana, Ora) %>%
  summarise(Totale_Tweet = n(), .groups = "drop")

# Heatmap
ggplot(dfHeatmap, aes(x = Ora, y = Giorno_Settimana, fill = Totale_Tweet)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "lightblue", high = "blue") +
  labs(
    title = "Distribuzione dei Tweet per Orario e Giorno della Settimana",
    x = "Ora del Giorno",
    y = "Giorno della Settimana",
    fill = "Totale Tweet"
  ) +
  theme_minimal()

Tramite la heatmap possiamo notare che gli utenti sono più attivi in determinate ore ovvero la mattina presto e fine pomeriggio, e nel weekned, possiamo dedurre che questi momenti sono strategici per pubblicare contenuti e massimizzare il coinvolgimento.

Motivo: Analizziamo la durata dell’attività degli utenti (in giorni attivi) per capire la persistenza nel tempo.

# **Durata dell'Attività**
# Istogramma di Giorni_Attivi
ggplot(dfUtenti, aes(x = Giorni_Attivi)) +
  geom_histogram(bins = 30, fill = "darkgreen", color = "white", alpha = 0.8) +
  labs(
    title = "Distribuzione della Durata dell'Attività degli Utenti",
    x = "Giorni Attivi",
    y = "Conteggio Utenti"
  ) +
  theme_minimal()

Il grafico mostra che la maggior parte degli utenti è attiva per un singolo giorno, possiamo dedurre che solo una minoranza degli utenti mantiene un’attività prolungata.

Motivo: Confrontiamo la durata dell’attività tra diverse classi di utenti per capire se gli utenti più attivi tendono a essere più persistenti.

# Boxplot per confrontare Giorni_Attivi tra le classi di attività
ggplot(dfUtenti, aes(x = Classe_Attivita, y = Giorni_Attivi, fill = Classe_Attivita)) +
  geom_boxplot(alpha = 0.7) +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Confronto della Durata dell'Attività tra Classi di Attività",
    x = "Classe di Attività",
    y = "Giorni Attivi"
  ) +
  theme_minimal()

Il grafico mostra una differenza significativa tra le classi, ad esempio con utenti molto attivi che hanno una durata maggiore, possiamo concludere che l’attività e la persistenza sono correlate.

Motivo: Vogliamo esplorare come il coinvolgimento totale (engagement) e relativo (proporzionale ai follower) variano rispetto al numero di follower degli utenti.

### **3. Analisi di Coinvolgimento**
# **Relazione tra Engagement e Follower**
# Scatter plot di Engagement_Totale vs. Followers_Max
ggplot(dfUtenti, aes(x = Followers_Max, y = Engagement_Totale)) +
  geom_point(color = "blue", alpha = 0.6) +
  labs(
    title = "Relazione tra Engagement Totale e Numero di Follower",
    x = "Numero Massimo di Follower",
    y = "Engagement Totale"
  ) +
  theme_minimal()

Se vediamo una tendenza crescente, significa che un numero maggiore di follower corrisponde a un maggiore engagement totale. Se i punti sono molto dispersi, potrebbe indicare che il numero di follower non è sempre un predittore affidabile dell’engagement.

Motivo: uguale

# Scatter plot di Engagement_Relativo vs. Followers_Max con fit lineare
ggplot(dfUtenti, aes(x = Followers_Max, y = Engagement_Relativo)) +
  geom_point(color = "darkorange", alpha = 0.6) +
  geom_smooth(method = "lm", color = "red", se = FALSE) +
  labs(
    title = "Relazione tra Engagement Relativo e Numero di Follower",
    x = "Numero Massimo di Follower",
    y = "Engagement Relativo"
  ) +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 248 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 49 rows containing missing values or values outside the scale range
## (`geom_point()`).

Se la linea di regressione è piatta o decrescente, potrebbe indicare che gli utenti con più follower hanno un engagement proporzionalmente inferiore rispetto a quelli con meno follower.

Motivo: Vogliamo confrontare il coinvolgimento relativo tra le diverse classi di attività degli utenti, filtrando eventuali outliers per avere una visione più chiara.

# **Engagement Relativo tra le Classi di Attività**
# Calcolo dei limiti per gli outliers
Q1 <- quantile(dfUtenti$Engagement_Relativo, 0.25, na.rm = TRUE)
Q3 <- quantile(dfUtenti$Engagement_Relativo, 0.75, na.rm = TRUE)
IQR_value <- Q3 - Q1

lower_limit <- Q1 - 1.5 * IQR_value
upper_limit <- Q3 + 1.5 * IQR_value

# Filtrare i dati senza outliers
dfUtenti_no_outliers <- dfUtenti %>%
  filter(Engagement_Relativo >= lower_limit & Engagement_Relativo <= upper_limit)

# Grafico aggiornato
ggplot(dfUtenti_no_outliers, aes(x = Classe_Attivita, y = Engagement_Relativo, fill = Classe_Attivita)) +
  geom_boxplot(alpha = 0.7) +
  scale_fill_brewer(palette = "Pastel1") +
  labs(
    title = "Engagement Relativo tra le Classi di Attività (Senza Outliers)",
    x = "Classe di Attività",
    y = "Engagement Relativo"
  ) +
  theme_minimal()

Se una classe ha valori medi di engagement relativi più alti, possiamo concludere che gli utenti in quella classe sono più efficaci nel generare coinvolgimento proporzionale al loro pubblico.

Motivo: Analizziamo l’engagement medio in termini di like e retweet per ogni classe di influenza per identificare i tipi di utenti più efficaci nel coinvolgere il pubblico.

# **Engagement Medio per Tipo di Utente**
# Preparazione dei dati per il Barplot
dfEngagementMedio <- dfUtenti %>%
  group_by(Classe_Influenza) %>%
  summarise(
    Media_Like_Per_Tweet = mean(Media_Like_Per_Tweet, na.rm = TRUE),
    Media_Retweet_Per_Tweet = mean(Media_Retweet_Per_Tweet, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  melt(id.vars = "Classe_Influenza", variable.name = "Tipo_Engagement", value.name = "Media_Engagement")

# Barplot delle medie di Media_Like_Per_Tweet e Media_Retweet_Per_Tweet per Classe_Influenza
ggplot(dfEngagementMedio, aes(x = Classe_Influenza, y = Media_Engagement, fill = Tipo_Engagement)) +
  geom_bar(stat = "identity", position = "dodge", alpha = 0.8) +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Engagement Medio per Tipo di Utente",
    x = "Classe di Influenza",
    y = "Media Engagement",
    fill = "Tipo di Engagement"
  ) +
  theme_minimal()

Se una classe di influenza mostra valori medi più elevati di like e retweet, possiamo dedurre che questo gruppo di utenti genera più coinvolgimento per singolo contenuto rispetto ad altri gruppi.

Motivo: Analizziamo la distribuzione delle classi di attività per comprendere la composizione degli utenti in termini di partecipazione e frequenza di attività.

### **4. Classificazione degli Utenti**

# **Grafico a torta o barre per la distribuzione delle Classi**
# Calcolo della distribuzione delle Classi di Attività
dfClasseAttivita <- dfUtenti %>%
  count(Classe_Attivita) %>%
  mutate(Percentuale = n / sum(n) * 100)

# Grafico a torta per Classe_Attivita
ggplot(dfClasseAttivita, aes(x = "", y = Percentuale, fill = Classe_Attivita)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar("y", start = 0) +
  scale_fill_brewer(palette = "Set3") +
  labs(
    title = "Distribuzione delle Classi di Attività",
    x = NULL, 
    y = NULL,
    fill = "Classe di Attività"
  ) +
  theme_minimal()

Tra le classi di attività troviamo alta e moderata, quest’ultima dominante sul primp

Motivo: Esaminiamo le classi di influenza per determinare quali gruppi di utenti sono più comuni in base alla loro capacità di influenzare il pubblico.

# Calcolo della distribuzione delle Classi di Influenza
dfClasseInfluenza <- dfUtenti %>%
  count(Classe_Influenza) %>%
  mutate(Percentuale = n / sum(n) * 100)

# Grafico a barre per Classe_Influenza
ggplot(dfClasseInfluenza, aes(x = Classe_Influenza, y = Percentuale, fill = Classe_Influenza)) +
  geom_bar(stat = "identity", alpha = 0.8) +
  scale_fill_brewer(palette = "Pastel2") +
  labs(
    title = "Distribuzione delle Classi di Influenza",
    x = "Classe di Influenza",
    y = "Percentuale",
    fill = "Classe di Influenza"
  ) +
  theme_minimal()

Osserviamo la classe di influenza “bassa” ha percentuali nettamente più alte, possiamo concludere che questo tipo di utente è più rappresentato nella piattaforma, mentre alta e moderata si equivalgono.

Motivo: Creiamo una heatmap per analizzare la relazione tra classi di attività e classi di influenza. Questo ci aiuta a individuare se esistono correlazioni significative tra il comportamento degli utenti e la loro capacità di influenzare.

# **Heatmap incrociata tra Classe_Attivita e Classe_Influenza**
# Tabella di contingenza
dfContingenza <- table(dfUtenti$Classe_Attivita, dfUtenti$Classe_Influenza)

# Conversione in formato long per ggplot
dfContingenzaLong <- as.data.frame(as.table(dfContingenza))

# Heatmap
ggplot(dfContingenzaLong, aes(Var1, Var2, fill = Freq)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  labs(
    title = "Heatmap tra Classi di Attività e Influenza",
    x = "Classe di Attività",
    y = "Classe di Influenza",
    fill = "Frequenza"
  ) +
  theme_minimal()

La combinazione classe di influenza bassa e classe di attività moderata hanno frequenze significativamente più alte, possiamo dedurre che determinate classi di attività tendono a essere associate a specifiche classi di influenza.

Motivo: Analizziamo i sentiment (positivo, neutro, negativo) medi per ogni classe di influenza per verificare se alcune classi hanno un tono predominante nei loro tweet.

### **5. Analisi di Sentiment**

# **Sentiment Medio per Utente**

# Boxplot di Sentiment_Pos, Sentiment_Neu, e Sentiment_Neg per le Classi di Influenza
dfUtenti <- dfUtenti %>%
  mutate(Data_Inizio = as.Date(Data_Inizio, format = "%Y-%m-%d"))

dfSentiment <- dfUtenti %>%
  select(Classe_Influenza, Sentiment_Pos, Sentiment_Neu, Sentiment_Neg) %>%
  pivot_longer(
    cols = starts_with("Sentiment"),
    names_to = "Tipo_Sentiment",
    values_to = "Valore_Sentiment"
  )

ggplot(dfSentiment, aes(x = Classe_Influenza, y = Valore_Sentiment, fill = Tipo_Sentiment)) +
  geom_boxplot(alpha = 0.7, outlier.color = "red", outlier.shape = 16) +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Sentiment Medio per Classe di Influenza",
    x = "Classe di Influenza",
    y = "Valore Sentiment",
    fill = "Tipo di Sentiment"
  ) +
  theme_minimal()
## Warning: Removed 57611 rows containing non-finite outside the scale range
## (`stat_boxplot()`).

Questo grafico ci permette di osservare se le classi con maggiore influenza mostrano sentiment più positivi o negativi, fornendo indicazioni sul loro impatto.

Motivo: Esaminiamo come i sentiment positivi e negativi sono cambiati nel tempo per identificare tendenze o eventi particolari che hanno influenzato l’umore degli utenti.

# Heatmap dell'intensità del sentiment (positivi vs. negativi) nel tempo
# Filtra per Tipo_Tweet "Normale"
dfSentimentTime <- dfUtenti %>%
  group_by(Data_Inizio) %>%
  summarise(
    Sentiment_Pos_Medio = mean(Sentiment_Pos, na.rm = TRUE),
    Sentiment_Neg_Medio = mean(Sentiment_Neg, na.rm = TRUE)
  ) %>%
  pivot_longer(
    cols = c(Sentiment_Pos_Medio, Sentiment_Neg_Medio),
    names_to = "Tipo_Sentiment",
    values_to = "Intensita_Sentiment"
  )

ggplot(dfSentimentTime, aes(x = Data_Inizio, y = Tipo_Sentiment, fill = Intensita_Sentiment)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  labs(
    title = "Heatmap dell'Intensità del Sentiment nel Tempo",
    x = "Data",
    y = "Tipo di Sentiment",
    fill = "Intensità"
  ) +
  theme_minimal() +
  scale_x_date(labels = date_format("%b %Y"))

I picchi di intensità nel sentiment negativo risultano più significativi, fornendo indizi sulle reazioni degli utenti.

Motivo: Indaghiamo se esiste una correlazione tra il sentiment degli utenti e il loro livello di coinvolgimento, considerando sia sentiment positivi che negativi.

# **Relazione tra Sentiment e Coinvolgimento**

# Scatter plot di Sentiment_Pos vs. Engagement_Totale
ggplot(dfUtenti, aes(x = Sentiment_Pos, y = Engagement_Totale)) +
  geom_point(alpha = 0.7, color = "darkgreen") +
  geom_smooth(method = "lm", color = "red", se = FALSE) +
  labs(
    title = "Relazione tra Sentiment Positivo e Coinvolgimento Totale",
    x = "Sentiment Positivo Medio",
    y = "Engagement Totale"
  ) +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 24032 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 24032 rows containing missing values or values outside the scale range
## (`geom_point()`).

# Scatter plot di Sentiment_Neg vs. Engagement_Totale
ggplot(dfUtenti, aes(x = Sentiment_Neg, y = Engagement_Totale)) +
  geom_point(alpha = 0.7, color = "darkred") +
  geom_smooth(method = "lm", color = "blue", se = FALSE) +
  labs(
    title = "Relazione tra Sentiment Negativo e Coinvolgimento Totale",
    x = "Sentiment Negativo Medio",
    y = "Engagement Totale"
  ) +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 9241 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 9241 rows containing missing values or values outside the scale range
## (`geom_point()`).

6. Analisi delle Interazioni

Motivo: La diversità delle interazioni misura il rapporto tra retweet e il totale delle interazioni, indicando quanto l’attività degli utenti è orientata verso la condivisione rispetto ad altri tipi di engagement.

# Creazione della variabile Diversità delle Interazioni
dfUtenti <- dfUtenti %>%
  mutate(Diversita_Interazioni = Totale_Retweet / Totale_Interazioni)

# Barplot di Diversità delle Interazioni per le diverse classi di influenza
ggplot(dfUtenti, aes(x = Classe_Influenza, y = Diversita_Interazioni, fill = Classe_Influenza)) +
  geom_bar(stat = "summary", fun = "mean", alpha = 0.7) +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Diversità delle Interazioni per Classe di Influenza",
    x = "Classe di Influenza",
    y = "Media Diversità delle Interazioni"
  ) +
  theme_minimal()

Questo barplot ci consente di osservare quali classi di influenza mostrano una tendenza più marcata verso il retweet rispetto ad altre forme di engagement. Classi di infulenza alta ha una diversità maggiore indicando un forte orientamento alla condivisione.

Motivo: Analizziamo la relazione tra la diversità delle interazioni e il totale delle interazioni per capire se utenti con più interazioni totali mostrano una diversità maggiore o minore.

# Scatter plot di Diversità delle Interazioni vs. Totale Interazioni
ggplot(dfUtenti, aes(x = Totale_Interazioni, y = Diversita_Interazioni, color = Classe_Influenza)) +
  geom_point(alpha = 0.7) +
  scale_color_brewer(palette = "Set2") +
  labs(
    title = "Diversità delle Interazioni vs. Totale Interazioni",
    x = "Totale Interazioni",
    y = "Diversità delle Interazioni"
  ) +
  theme_minimal()
## Warning: Removed 1735 rows containing missing values or values outside the scale range
## (`geom_point()`).

Il grafico a dispersione ci permette di osservare se gli utenti più attivi (con un totale di interazioni maggiore) mostrano un comportamento diverso in termini di diversità delle interazioni rispetto a quelli meno attivi. Ad esempio, possiamo verificare se utenti con molte interazioni si concentrano su un unico tipo di engagement o mantengono un mix bilanciato.

# # Filtro degli utenti con alta Diversità delle Interazioni
# soglia_diversita <- quantile(dfUtenti$Diversita_Interazioni, 0.75, na.rm = TRUE)
# dfUtentiAlti <- dfUtenti %>% 
#   filter(Diversita_Interazioni >= soglia_diversita)
# 
# # Creazione di una rete simulata: matrice di adiacenza basata sulle interazioni
# # Simulazione per utenti selezionati
# set.seed(42)
# num_utenti <- nrow(dfUtentiAlti)
# matrice_adiacenza <- matrix(sample(0:1, num_utenti^2, replace = TRUE, prob = c(0.95, 0.05)), 
#                             nrow = num_utenti, ncol = num_utenti)
# rownames(matrice_adiacenza) <- dfUtentiAlti$username
# colnames(matrice_adiacenza) <- dfUtentiAlti$username
# 
# # Creazione dell'oggetto grafo
# grafo <- graph_from_adjacency_matrix(matrice_adiacenza, mode = "undirected", diag = FALSE)
# 
# # Aggiunta di attributi ai nodi
# V(grafo)$Diversita_Interazioni <- dfUtentiAlti$Diversita_Interazioni
# V(grafo)$size <- dfUtentiAlti$Diversita_Interazioni * 10  # Dimensioni proporzionali
# 
# # Visualizzazione del grafo
# plot(
#   grafo,
#   vertex.size = V(grafo)$size,
#   vertex.label = V(grafo)$name,
#   vertex.color = "skyblue",
#   edge.color = "gray",
#   main = "Grafico della Rete Sociale (Alta Diversità delle Interazioni)"
# )

7. Confronto tra Classi

Motivo: Analizzare come le diverse classi di attività si differenziano in termini di volume complessivo di tweet.

# Boxplot per Engagement_Totale suddiviso per Classe_Influenza
ggplot(dfUtenti, aes(x = Classe_Influenza, y = Engagement_Totale, fill = Classe_Influenza)) +
  geom_boxplot(alpha = 0.7, outlier.shape = NA) +
  scale_fill_brewer(palette = "Set3") +
  labs(
    title = "Engagement Totale per Classe di Influenza",
    x = "Classe di Influenza",
    y = "Engagement Totale"
  ) +
  theme_minimal()

Mostra come le classi di influenza influenzano l’engagement totale. Le differenze tra mediane e ampiezza delle distribuzioni indicano variazioni significative.

Motivo: Confrontare la distribuzione dei follower massimi tra le diverse classi di attività per identificare schemi o anomalie.

# Violin plot per Followers_Max suddiviso per Classe_Attivita
ggplot(dfUtenti, aes(x = Classe_Attivita, y = Followers_Max, fill = Classe_Attivita)) +
  geom_violin(alpha = 0.7, trim = TRUE) +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Distribuzione dei Massimi Followers per Classe di Attività",
    x = "Classe di Attività",
    y = "Massimo Followers"
  ) +
  theme_minimal()

Confronta la distribuzione dei follower massimi per le classi di attività, evidenziando densità e variazioni tra le classi.

Motivo: Visualizzare la relazione tra il numero medio di tweet giornalieri e le classi di attività, esplorando la loro variabilità.

# Attività Relativa e Tweet Giornalieri: Scatter plot
ggplot(dfUtenti, aes(x = Tweet_Giornalieri_Medi, y = Classe_Attivita, color = Classe_Attivita)) +
  geom_jitter(alpha = 0.6) +
  scale_color_brewer(palette = "Dark2") +
  labs(
    title = "Attività Relativa: Tweet Giornalieri Medi per Classe di Attività",
    x = "Tweet Giornalieri Medi",
    y = "Classe di Attività"
  ) +
  theme_minimal()

Esplora la variabilità nei tweet giornalieri medi per classe di attività, evidenziando il comportamento di gruppi diversi.

8. Analisi Avanzate (se applicabile)

La heatmap ci permette di identificare visivamente la forza e la direzione delle relazioni lineari tra le variabili quantitative nel dataset. È utile per comprendere quali variabili sono fortemente correlate, debolmente correlate o non correlate tra loro.

# Preparazione del dataset per l'analisi
dfQuantitative <- dfUtenti %>%
  select(Totale_Tweet, Engagement_Totale, Followers_Max, Totale_Like, Totale_Retweet, Tweet_Giornalieri_Medi) %>%
  na.omit()



# Matrice di correlazione
correlation_matrix <- cor(dfQuantitative, use = "pairwise.complete.obs")
correlation_matrix <- correlation_matrix[-nrow(correlation_matrix), -ncol(correlation_matrix)]


# Heatmap delle correlazioni
heatmaply::heatmaply(
  correlation_matrix,
  main = "Heatmap delle Correlazioni",
  xlab = "Variabili Quantitative",
  ylab = "Variabili Quantitative",
  colors = colorRampPalette(c("blue", "white", "red"))(200),
  limits = c(-1, 1)
)
# Visualizzazione con corrplot
corrplot(correlation_matrix, method = "circle", type = "upper", tl.cex = 0.8, 
         main = "Matrice delle Correlazioni")

Le variabili fortemente correlate positive (ad esempio, Totale Retweet e Engagement Totale) possono indicare metriche che si influenzano direttamente. Le correlazioni negative (se presenti) potrebbero suggerire metriche che si oppongono nel comportamento. La mancanza di correlazione (vicino a 0) tra alcune variabili può indicare indipendenza tra di esse, fornendo indicazioni su quali metriche siano più rappresentative o uniche. Questo aiuta nella scelta di metriche rilevanti per ulteriori analisi o modelli.

Questo grafico visualizza come i gruppi (cluster) si distribuiscono nello spazio bidimensionale delle prime due componenti principali. La PCA consente di ridurre la dimensionalità e di rappresentare i dati in modo più comprensibile, mentre la clusterizzazione aiuta a identificare gruppi omogenei.

# Clusterizzazione degli utenti (K-means)
set.seed(123) # Per riproducibilità
k <- 3 # Numero di cluster scelto


# Normalizzazione dei dati
dfCluster <- scale(dfQuantitative)
dfCluster <- as.data.frame(dfCluster)
dfCluster <- dfCluster %>% select(-Tweet_Giornalieri_Medi)

# Algoritmo K-means
kmeans_result <- kmeans(dfCluster, centers = k, nstart = 25)

# Aggiunta dei cluster al dataset originale
dfUtenti <- dfUtenti %>%
  mutate(Cluster = as.factor(kmeans_result$cluster))

# Visualizzazione dei cluster (scatter plot delle prime due variabili PCA)
library(ggfortify)
## Warning: il pacchetto 'ggfortify' è stato creato con R versione 4.4.2
autoplot(prcomp(dfCluster), data = dfUtenti, colour = 'Cluster') +
  labs(
    title = "Clusterizzazione degli Utenti (K-means)",
    x = "Componente Principale 1",
    y = "Componente Principale 2"
  ) +
  theme_minimal()

I cluster ben separati indicano che i gruppi di utenti hanno caratteristiche distinte. La sovrapposizione tra cluster potrebbe suggerire che i dati non supportano una segmentazione netta, o che il numero di cluster scelto non è ottimale. Le posizioni relative dei cluster nello spazio PCA possono fornire indicazioni su quali caratteristiche distinguono un gruppo dall’altro.